<h1>Convert elapsed timestamps, like, "in 3 minutes!"</h1>
<p style="margin-top: 10px; margin-bottom: 0px;">PrettyTime is an OpenSource time formatting library. Completely customizable, PrettyTime creates human readable, relative timestamps like those seen on Digg, Twitter, and Facebook. It's simple, get started "right now!"</p>
<p style="margin-bottom: 10px;">
<table style="margin-bottom: 15px; border: dotted 1px; padding: 10px; background: #555; color: #fff;" border="0" width="100%">
<tbody>
<tr>
<td width="50%">
<h3 style="font-size: 140%; margin-bottom: 5px;">Downloads: ↓ (LGPL3)</h3>
<p style="padding-left: 30px;"><strong>1.0.2:</strong> <a href="http://prettytime.googlecode.com/files/ocpsoft-pretty-time-1.0.2.jar">jar</a>, <a href="http://prettytime.googlecode.com/files/ocpsoft-pretty-time-1.0.2-sources.jar">src</a>, <a target="_blank" href="http://ocpsoft.com/api/ocpsoft-pretty-time/1.0.2/">api</a></p>
<p style="padding-left: 30px;"><a href="http://ocpsoft.com/repository/com/ocpsoft/ocpsoft-pretty-time/">All Downloads / Maven Repo</a></p>

<h4 style="padding-left: 30px; margin-top: 10px; margin-bottom: 5px;">Dependencies:</h4>
<p style="padding-left: 30px;">Java 5.0 and up</p>

<h4 style="margin-top: 10px;"><strong>Coming eventually:</strong></h4>
i18n (need help: please send in your designs!)</td>
<td style="text-align: justify; text-justify: newspaper">Please <a href="http://code.google.com/p/prettytime/issues/entry" target="_blank">open an issue</a> if you have any suggestions, or any difficulties.
<br/>
View the <a href="#docs">documentation</a>.</td>
</tr></tbody></table>
<h4>From <a href="http://twitter.com/ocpsoft">@ocpsoft</a> and <a href="http://twitter.com/lincolnthree">@lincolnthree</a></h4>
<br/>
<h1>Features:</h1>
<ol>
	<li>Generate human-readable timestamps like, "right now", "2 days ago", or "3 months from now"</li>
	<li>Simple single interface - easy to learn.</li>
	<li>Entirely customizable. Provide your own TimeUnit and TimeFormat objects for complete control.</li>
	<li>Provided integration for the JSF web-application framework (if you would like to include another, <a href="http://ocpsoft.com/contact/">contact us</a>)</li>
</ol>
<a name="docs"></a>
<h2>Documentation:</h2>
Using PrettyTime is simple.
<!--more-->
<ol>
	<li><a href="#basic">Basic use in a Java App</a><br /></li>
	<li><a href="#customunit">Creating a custom TimeUnit</a><br /></li>
	<li><a href="#jsf">Using PrettyTimeConverter in JSF</a><br/></li>
	<li><a href="#examples">Examples using JUnit</a></li>
</ol>

<h3 style="margin-bottom: 15px;"><a href="#configuration"><strong>0. Extract necessary JAR files into your /WEB-INF/lib directory</strong></a></h3>
This step is pretty straight-forward, right?
<h4>or include a maven dependency in your pom.xml (optional)</h4>
<pre lang="xml">
<dependency>
	<groupId>com.ocpsoft</groupId>
	<artifactId>ocpsoft-pretty-time</artifactId>
	<version>1.0.2</version>
</dependency>
</pre>

<h3><a name="basic"></a><a href="#docs"><strong>Basic use in a Java App:</strong></a></h3>
<p>PrettyTime, by default, uses the current time as the point of reference (reference time) for calculating the elapsed, or remaining time to the Date argument.</p>
<pre lang="java">import java.util.Date;
import com.ocpsoft.pretty.time.PrettyTime;

public class BasicJavaApp
{
	public static void main(String[] args) 
	{
		PrettyTime p = new PrettyTime();
		System.out.println(p.format(new Date()));
	}
}</pre>
<p>Prints: "right now"</p>
<h4>See below for more <a href="#examples">examples</a> using JUnit.</h4>
<p/><br/>

<h3><a name="customunit"></a><a href="#docs"><strong>Creating a custom TimeUnit:</strong></a></h3>
<p>TimeUnits are the units of measure in PrettyTime. They can be as long or as short as desired, and can be formatted into any necessary pattern. All that needs to be done is to implement the TimeUnit interface, and provide a default TimeFormat</p>
<pre lang="java">package com.ocpsoft.pretty.time.units;

import com.ocpsoft.pretty.time.BasicTimeFormat;
import com.ocpsoft.pretty.time.TimeFormat;
import com.ocpsoft.pretty.time.TimeUnit;

public class Month implements TimeUnit
{
    private static final TimeFormat defaultFormat = new BasicTimeFormat().setPattern("%n %u").setPastSuffix(" ago")
            .setFutureSuffix(" from now");

    private TimeFormat format = defaultFormat;
    private long maxQuantity = 0;
    private final long millisPerUnit = 2629743830L;
    private String name = "month";
    private String pluralName = "months";
    
    /* getters and setters */
}
</pre>
<p>TimeFormat is also simple -- and is the core of the Formatting platform.</p>
<pre lang="java">package com.ocpsoft.pretty.time;

public interface TimeFormat
{
    /**
     * Given a populated Duration object. Apply formatting and output the
     * result.
     */
    public abstract String format(final Duration duration);
}
</pre>
<p>See BasicTimeFormat for an implementation example using regular expressions</p>
<br/>

<h3><a name="jsf"></a><a href="#docs"><strong>Using PrettyTimeConverter in JSF:</strong></a></h3>
<p>PrettyTime includes a JSF Converter for easy output formatting. No additional configuration is required to use this object, since PrettyTime includes its own META-INF/faces-config.xml -- Just include the PrettyTime jar file on your classpath.</p>
<pre lang="xml">
<h:outputText value="#{exampleBean.futureDate}">
	<f:converter converterId="com.ocpsoft.PrettyTimeConverter"/>
</h:outputText>
</pre>
<p>In this example, futureDate must be a valid java.util.Date object.</p>
<br/>

<h3><a name="examples"></a><a href="#docs"><strong>Examples using JUnit:</strong></a></h3>
<p>See below for creating custom time units and formats:</p>
<pre lang="java">import static org.junit.Assert.assertEquals;
import java.util.Date;
import org.junit.Test;

public class PrettyTimeTest
{
    @Test
    public void testRightNow() throws Exception
    {
        PrettyTime t = new PrettyTime(new Date(0));
        assertEquals("right now", t.format(new Date(6000)));
    }

    @Test
    public void testMinutesFromNow() throws Exception
    {
        PrettyTime t = new PrettyTime(new Date(0));
        assertEquals("12 minutes from now", t.format(new Date(1000 * 60 * 12)));
    }

    @Test
    public void testCustomFormat() throws Exception
    {
        PrettyTime t = new PrettyTime(new Date(0));
        t.setUnits(new TimeUnit()
        {

            public TimeFormat getFormat()
            {
                return new BasicTimeFormat().setPattern("%n %u").setRoundingTolerance(20).setFutureSuffix("... RUN!")
                        .setFuturePrefix("self destruct in: ").setPastPrefix("self destruct was: ").setPastSuffix(
                                " ago...");
            }

            public long getMaxQuantity()
            {
                return 0;
            }

            public long getMillisPerUnit()
            {
                return 5000;
            }

            public String getName()
            {
                return "tick";
            }

            public String getPluralName()
            {
                return "ticks";
            }
        });
        assertEquals("self destruct in: 5 ticks... RUN!", t.format(new Date(25000)));
        t.setReference(new Date(25000));
        assertEquals("self destruct was: 5 ticks ago...", t.format(new Date(0)));
    }
    
    @Test
    public void testHoursFromNow() throws Exception
    {
        PrettyTime t = new PrettyTime(new Date(0));
        assertEquals("3 hours from now", t.format(new Date(1000 * 60 * 60 * 3)));
    }

    @Test
    public void testDaysFromNow() throws Exception
    {
        PrettyTime t = new PrettyTime(new Date(0));
        assertEquals("3 days from now", t.format(new Date(1000 * 60 * 60 * 24 * 3)));
    }

    @Test
    public void testWeeksFromNow() throws Exception
    {
        PrettyTime t = new PrettyTime(new Date(0));
        assertEquals("3 weeks from now", t.format(new Date(1000 * 60 * 60 * 24 * 7 * 3)));
    }

    @Test
    public void testMonthsFromNow() throws Exception
    {
        PrettyTime t = new PrettyTime(new Date(0));
        assertEquals("3 months from now", t.format(new Date(2629743830L * 3L)));
    }

    @Test
    public void testYearsFromNow() throws Exception
    {
        PrettyTime t = new PrettyTime(new Date(0));
        assertEquals("3 years from now", t.format(new Date(2629743830L * 12L * 3L)));
    }

    @Test
    public void testDecadesFromNow() throws Exception
    {
        PrettyTime t = new PrettyTime(new Date(0));
        assertEquals("30 years from now", t.format(new Date(315569259747L * 3L)));
    }

    @Test
    public void testCenturiesFromNow() throws Exception
    {
        PrettyTime t = new PrettyTime(new Date(0));
        assertEquals("300 years from now", t.format(new Date(3155692597470L * 3L)));
    }

    /*
     * Past
     */
    @Test
    public void testMomentsAgo() throws Exception
    {
        PrettyTime t = new PrettyTime(new Date(6000));
        assertEquals("moments ago", t.format(new Date(0)));
    }

    @Test
    public void testMinutesAgo() throws Exception
    {
        PrettyTime t = new PrettyTime(new Date(1000 * 60 * 12));
        assertEquals("12 minutes ago", t.format(new Date(0)));
    }

    @Test
    public void testHoursAgo() throws Exception
    {
        PrettyTime t = new PrettyTime(new Date(1000 * 60 * 60 * 3));
        assertEquals("3 hours ago", t.format(new Date(0)));
    }

    @Test
    public void testDaysAgo() throws Exception
    {
        PrettyTime t = new PrettyTime(new Date(1000 * 60 * 60 * 24 * 3));
        assertEquals("3 days ago", t.format(new Date(0)));
    }

    @Test
    public void testWeeksAgo() throws Exception
    {
        PrettyTime t = new PrettyTime(new Date(1000 * 60 * 60 * 24 * 7 * 3));
        assertEquals("3 weeks ago", t.format(new Date(0)));
    }

    @Test
    public void testMonthsAgo() throws Exception
    {
        PrettyTime t = new PrettyTime(new Date(2629743830L * 3L));
        assertEquals("3 months ago", t.format(new Date(0)));
    }
    
    @Test
    public void testYearsAgo() throws Exception
    {
        PrettyTime t = new PrettyTime(new Date(2629743830L * 12L * 3L));
        assertEquals("3 years ago", t.format(new Date(0)));
    }

    @Test
    public void testDecadesAgo() throws Exception
    {
        PrettyTime t = new PrettyTime(new Date(315569259747L * 3L));
        assertEquals("30 years ago", t.format(new Date(0)));
    }

    @Test
    public void testCenturiesAgo() throws Exception
    {
        PrettyTime t = new PrettyTime(new Date(3155692597470L * 3L));
        assertEquals("300 years ago", t.format(new Date(0)));
    }
}
</pre>
<br/>